import type { DeviceID } from "@zwave-js/config";
import type { RFRegion } from "@zwave-js/core";
import type { Expand } from "@zwave-js/shared";

export type RebuildRoutesStatus = "pending" | "done" | "failed" | "skipped";

export interface RebuildRoutesOptions {
	/** Whether the routes of sleeping nodes should be rebuilt too at the end of the process. Default: true */
	includeSleeping?: boolean;
	/** Whether nodes with priority return routes should be included, as those will be deleted. Default: false */
	deletePriorityReturnRoutes?: boolean;
}

export type SDKVersion =
	| `${number}.${number}`
	| `${number}.${number}.${number}`;

export interface FirmwareUpdateFileInfo {
	target: number;
	url: string;
	integrity: `sha256:${string}`;
}

/** The information sent to the firmware update service to identify which updates are available for a device. */
export type FirmwareUpdateDeviceID = Expand<
	DeviceID & {
		firmwareVersion: string;
		rfRegion?: RFRegion;
	}
>;

export interface FirmwareUpdateServiceResponse {
	version: string;
	changelog: string;
	channel: "stable" | "beta";
	files: FirmwareUpdateFileInfo[];
	downgrade: boolean;
	normalizedVersion: string;
	region?: string;
}

/** Response from API v4 bulk request */
export interface FirmwareUpdateBulkInfo {
	manufacturerId: string;
	productType: string;
	productId: string;
	firmwareVersion: string;
	updates: FirmwareUpdateServiceResponse[];
}

export type FirmwareUpdateInfo = Expand<
	FirmwareUpdateServiceResponse & {
		/** Which device this update is for */
		device: FirmwareUpdateDeviceID;
	}
>;

export function isFirmwareUpdateInfo(
	info: any,
): info is FirmwareUpdateInfo {
	return typeof info === "object"
		&& info !== null
		&& typeof info.version === "string"
		&& typeof info.normalizedVersion === "string"
		&& typeof info.changelog === "string"
		&& typeof info.channel === "string"
		&& typeof info.device === "object"
		&& info.device !== null
		&& typeof info.device.manufacturerId === "number"
		&& typeof info.device.productType === "number"
		&& typeof info.device.productId === "number"
		&& typeof info.device.firmwareVersion === "string";
}

export interface GetFirmwareUpdatesOptions {
	/** Allows overriding the API key for the firmware update service */
	apiKey?: string;
	/** Allows adding new components to the user agent sent to the firmware update service (existing components cannot be overwritten) */
	additionalUserAgentComponents?: Record<string, string>;
	/** Whether the returned firmware upgrades should include prereleases from the `"beta"` channel. Default: `false`. */
	includePrereleases?: boolean;
	/**
	 * Can be used to specify the RF region if the Z-Wave controller
	 * does not support querying this information.
	 *
	 * **WARNING:** Specifying the wrong region may result in bricking the device!
	 *
	 * For this reason, the specified value is only used as a fallback
	 * if the RF region of the controller is not already known.
	 */
	rfRegion?: RFRegion;
}
